2021 津门杯&红帽杯re部分复现

在军训,比赛快结束时看了看题,做不来,完全做不来,复现学习,复现了简单的3道题,其他题确实能力还不行,下载做题工具时,还中毒了。。。。

GoodRE

这个题的难点就在于函数名不知道,一个tea加密,有点不一样的是,里面的一些加,除,位移都用了一些大数函数,导致看起来不像tea加密,而且把dealt给分为了两个数的xor,特征也没有了。

ida分析

接下来看8个字符转16进制的函数

然后就是tea内部

脚本

#include<stdio.h>

void decrypt(unsigned int *code , unsigned int *key)
{
    unsigned int delta=0x9e3779b9;
    unsigned int v0,v1,sum=0xC6EF3720,i;// sum=0xC6EF3720

    v0=code[0];
    v1=code[1];
    for(i=0;i<32;i++)
    {
        v1-=( (v0<<4)+key[2] ) ^ (v0+sum) ^ ( (v0>>5)+key[3] );
        v0-=( (v1<<4)+key[0] ) ^ (v1+sum) ^ ( (v1>>5)+key[1] );
        sum-=delta;
    }
    code[0]=v0;
    code[1]=v1;
    printf("%X%X",code[0],code[1]);
}


int main()
{
    unsigned int key[4]={17,17,17,17};
    unsigned int code[8]={0x79AE1A3B,0x596080D3,0x80E03E80, 0x846C8D73, 0x21A01CF7, 0xC7CACA32, 0x45F9AC14, 0xC5F5F22F};
    int i; 

    printf("flag{");
    for(i=0;i<4;i++)
    {
        decrypt(&code[i*2],key);
    }
    printf("}"); 
}
//flag{7DEA3F6D3B3D6C0C620864ADD2FA2AE1A61F2736F0060DA0B97E8356D017CE59} 

easyRe

这道题的考点是,爆破,z3,和c语言调用lua文件中的函数。题目给了3个文件,output.txt不知道什么用。

ida流程

看看处理函数

所以先解密my.lua文件

#include<stdio.h>

int main()
{
    FILE *p;
    char v[0x170]={0};
    char m[8]="cgfffce";
    int v4[3]={2,3,5};
    int i;

    p=fopen("my.lua","rb");
    fread(&v, 1, 0x16f, p);
    for(i=0;i<0x16f;i++)
    {
        v[i]=v[i]^v4[i%3];
    }
    FILE *p1 = fopen("my.txt", "wb");
    fwrite(&v, 1, 0x16f, p1);

    for(i=0;i<7;i++)
    {
        m[i]=m[i]^v4[i%3];
        printf("%c",m[i]);
    }
 } 
//adcdefg

得到的my.txt,就是一个异或。

function BitXOR(a,b)
    local p,c=1,0
    while a>0 and b>0 do
        local ra,rb=a%2,b%2
        if ra~=rb then c=c+p end
        a,b,p=(a-ra)/2,(b-rb)/2,p*2
    end
    if a<b then a=b end
    while a>0 do
        local ra=a%2
        if ra>0 then c=c+p end
        a,p=(a-ra)/2,p*2
    end
    return c
end

function adcdefg(j)  
    return BitXOR(5977654,j)
end

用z3写的python脚本如下

from z3 import *
code=[5977672,338,5978023,3630,5977188,524,5977313,4067,5977511,207,5973801,3662,5977375,42,5974494,8361,5978164,988,5976337,12273,5976967,6871,5979438,5916,5976793,1485,5978936,8243,5974126,3027,5969737,9510,684,5973999,3840,5978418,13036,5975191,11850,5979906,7247,5978814,12173,5976318,1252,5974940,5736,5969435,757,5973565,4036,5979036,7999,5973024,859,5973093,3278,5973550,3179,5976631,3699,5977985,373,5977828]
def decode(table):
    s = Solver()
    flag = [BitVec(('x%d' % i), 8) for i in range(32)]
    mid=[0]*64
    for j in range(32):
        for k in range(33):
            mid[j+k]+=(flag[j]^table[k])
            mid[j+k]=mid[j+k]^5977654

    for i in range(64):
        s.add(mid[i]==code[i])

    if s.check() == sat:
        model = s.model()
        str = [chr(model[flag[i]].as_long().real) for i in range(32)]
        print("".join(str))
        exit()
    else:
        print("no_sat")

def creat_seedtable(seed):
    s=[0]*33
    for i in range(33):
        s[i]=(32310901 * seed + 1729) % 254
        seed=s[i]
    return s

for i in range(0xff):
    table=creat_seedtable(i)
    print(i)
    print(table)
    decode(table)
//45c48cce2e2d7fbdea1afc51c7c6ad26

红帽杯-ezRev

一个变换key的xtea加密,中间有许多错误的比较和判断,需要自己patch这些点,然后动调出key,并且里面很多函数的名称也不知道,增加了难度。

ida看流程

第一个patch,if判断

第二个patch,根据动调来看,两个随机数,前一个数要大于后一个数,并且都小于10。最终来看是需要两个rand随机数必须是4,2,才能通过后面的判断。

经过不断的试rand的值,终于发现了判断的要求

假设rand1=a,rand2=b,a**b转化为2进制的长度为len1,b**a转换为2进制的长度为len2,需要满足len1>>2==len2>>2。

例子1:
a=8
b=4
len1=20
len2=16
不行,会exit

例子2:
a=4
b=2
len1=8
len2=8
ok

所以当a ** b == b ** a时,是一定会满足的,但是由于有>>2的缘故,也不知道会不会有其他值来满足这个条件,但是4,2一定是满足的。

获得key

tea加密

解密

#include<stdio.h>
void decrypt(unsigned int r ,unsigned int *code ,unsigned int *key)
{
    unsigned int v0,v1,i,delta=0x9e3779b9;
    unsigned int sum=delta*r;

    v0=code[0];
    v1=code[1];
    for(i=0;i<r;i++)
    {
        v1-=( ((v0<<4) ^(v0>>5)) +v0 ) ^ ( sum + key[ (sum>>11)&3 ]);
        sum-=delta;
        v0-=( ((v1<<4) ^ (v1>>5)) +v1 ) ^ ( sum + key[sum&3] );
    }
    code[0]=v0;
    code[1]=v1;

    key[0]+=789;
    key[3]+=135;
    printf("%c%c",code[0],code[1]);
}


int main()
{
    unsigned int key[4]={0x00067932, 0x0004F765, 0x0007FAFF, 0x00067932};
    unsigned int r=32;
    unsigned int code[16]={0xd118c7b2,0x7fc3f3a8,0x4a19f2da,0x472469e1,0x7c682864,0x50c0e3d1,0xc595670b,0x2ee07578,0xd040a3f0,0xc5590286,0xd82b07a8,0xd5978c2c,0x4e2bc556,0x079e2e90,0xc7a353b5,0x493995B};
    int i;

    for(i=0;i<8;i++)
    {
        decrypt(r,&code[i*2],key);
    }
} 

动调getflag